#=============================================================================
'''
    simplesurvey

    Provides unit-test harness for basemodule.py and its derived csmodules.
    Testing implementation of Surveyor that exercises the cs module code
    separate from most of the surveyor framework; in particular:

        -- No multiprocessing, threading, or job structure
        -- No surveyor options and config file processing
        -- Limited output support
'''
#=============================================================================
# Copyright 2011, Matt Peloquin. This file is part of Code Surveyor,
# covered under GNU GPL v3 and is distributed WITHOUT ANY WARRANTY
#=============================================================================
import os
import sys
import time

import test_syspathfix
from framework import basemodule
from framework import modules
from framework import fileext
from framework import configentry
from framework import trace
from csmodules import *


_output = None


def simple_survey(pathToMeasure, configEntries, output, traceLevel, traceModes):
    '''
    Simple surveyor implementation that loads modules and then walks the given
    path and calls modules based on the moduleFileAssociations
    '''
    global _output
    _output = output

    _output.write("Simple Surveyor\n")
    _output.write("Measuring: {0}\n".format(pathToMeasure))
    for configItem, configText in configEntries:
        _output.write("With: {0}\n".format(str(configItem), configText))
    trace.init_context(level=traceLevel, modes=traceModes, out=_output)

    entries = []
    moduleLoader = modules.CodeSurveyorModules()
    for entry, extraParams in configEntries:
        entry.module = moduleLoader.get_csmodule(entry.moduleName, entry.options)
        entry.rawParams = extraParams
        entry.processedParams = extraParams
        entries.append(entry)

    for currentDir, childDirs, fileNames in os.walk(pathToMeasure):
        _output.write("{0}\n".format(currentDir))
        _output.write("========================\n")
        measure_files(currentDir, entries, fileNames)


def measure_files(currentDir, entries, fileNames):
    '''
    For each filename, measure the file with the csmodules associated
    with its extension
    '''
    for fileName in fileNames:
        _, ext = os.path.split(fileName)
        for entry in entries:
            for fileFilter in entry.fileFilters:
                if fileext.file_ext_match(ext, fileFilter):
                    measure_file(os.path.join(currentDir, fileName), entry)


def measure_file(fileName, configItem):
    '''
    Open the file and measure it using the csmodule
    '''
    csmodule = configItem.module
    fileHandle = csmodule.open_file(fileName, None)
    csmodule.process_file(fileName, fileHandle, configItem, 1, measure_callback)
    fileHandle.close()


def measure_callback(filePath, measureResults, analysisResults):
    '''
    Synchronus callback from the module with results
    '''
    _output.write("   {0}\n".format(filePath))
    _output.write("      {0}\n".format(measureResults))
    for result in analysisResults:
        _output.write("          {0}\n".format(result))


# ----------------------------------------------------------------------------
# simple_survey is designed to be run from unit tests, but we allow for some
# some limited command-line testing to console
if __name__ == '__main__':
    timeStart = time.time()

    # Metadata output options
    MetaDataOptions = {
        'NAME': None,
        'DIRS': 3,
        'TAGS': None,
        }

    try:
        pathToMeasure = '.'
        if len(sys.argv) > 1:
            pathToMeasure = sys.argv[1]
        print "SimpleSurvey Measuring: {0}".format(pathToMeasure)

        # Setup a static config entry list; this allows us to bypass
        # use of the configstack
        configStr = 'measure NBNC * *'
        if len(sys.argv) > 2 and sys.argv[2] != '-':
            configStr = sys.argv[2]
        configEntry = configentry.ConfigEntry(configStr)
        configEntry.options.append(('METADATA', MetaDataOptions))
        configEntries = [(configEntry, [])]
        print "SimpleSurvey Config: {0}".format(configStr)

        traceLevel = 1
        if len(sys.argv) > 3:
            traceLevel = sys.argv[3]
            print "TraceLevel: {0}".format(traceLevel)
        traceModes = []
        if len(sys.argv) > 4:
            print "TraceMode: {0}".format(sys.argv[4])
            try:
                traceModes = eval(sys.argv[4])
            except:
                print """Error evaluating TraceMode, should eval list like: "['nbnc']" """

        simple_survey(pathToMeasure, configEntries, sys.stdout, traceLevel, traceModes)

        print "SimpleSurvey Complete: {0:.1f} seconds".format(time.time() - timeStart)
    except:
        trace.traceback()
